package com.xbd.wxpay.controller;





import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;


import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;



@Slf4j
@RestController
@RequestMapping("/index")
public class IndexController {

    public static String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
    public static String getOrderNo(){

        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMddHHmmss");
        String time = ft.format(new Date());
        int mathCode = (int) ((Math.random() * 9 + 1) * 10000);// 5位随机数
        String resultCode = time+mathCode;
        return resultCode;
    }
    /**
     * 签名字符串
     * @param text 需要签名的字符串
     * @param key 密钥
     * @param input_charset 编码格式
     * @return 签名结果
     */
    public static String sign(String text, String key, String input_charset) {
        text = text + "&key=" + key;
        System.out.println(text);

        return DigestUtils.md5DigestAsHex(getContentBytes(text, input_charset));
    }
    /**
     * @param content
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     */
    public static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
        }
    }
    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {// 拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }
    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes());
    }
    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }

        return sb.toString();
    }


    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点，则此节点的值是子节点的xml数据。
     */
    public static Map doXMLParse(String strxml) throws Exception {
        if(null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();
        InputStream in = String2Inputstream(strxml);
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }

            m.put(k, v);
        }
        in.close();

        return m;
    }

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(method = RequestMethod.GET,value = "/pay")
    public String login() throws Exception {


        String url ="https://api.mch.weixin.qq.com/pay/unifiedorder";
        String out_trade_no = getOrderNo();

        HttpHeaders requestHeader = new HttpHeaders();
        requestHeader.setContentType(MediaType.APPLICATION_XML);
        String key ="1a0sh2jtW47wbnxzemTC1ZUQHiKKhJEL";
        String appid="wx9622abe3015f6393";
        String attach="1";
        String body="123";
        String mch_id="1531380651";
        String nonce_str=getRandomStringByLength(13);
        String notify_url="http://www.domopluses.com/wx_notify";
        String product_id="12345";

        String spbill_create_ip="127.0.0.1";
        String total_fee="1";
        String trade_type="APP";

        Map<String, String> packageParams = new HashMap<>();
        packageParams.put("appid",appid);
        packageParams.put("attach",attach);
        packageParams.put("body",body);
        packageParams.put("mch_id",mch_id);
        packageParams.put("nonce_str",nonce_str);
        packageParams.put("notify_url",notify_url);
        packageParams.put("product_id",product_id);
        packageParams.put("total_fee",total_fee);
        packageParams.put("out_trade_no",out_trade_no);
        packageParams.put("spbill_create_ip",spbill_create_ip);
        packageParams.put("trade_type",trade_type);


        String prestr = createLinkString(packageParams);
        String sign= sign(prestr, key, "utf-8").toUpperCase();


        StringBuffer xmlString = new StringBuffer();
        xmlString.append("<xml>");

        xmlString.append("<appid>");
        xmlString.append(appid);
        xmlString.append("</appid>");

        xmlString.append("<attach>");
        xmlString.append(attach);
        xmlString.append("</attach>");

        xmlString.append("<body>");
        xmlString.append(body);
        xmlString.append("</body>");

        xmlString.append("<mch_id>");
        xmlString.append(mch_id);
        xmlString.append("</mch_id>");

        xmlString.append("<nonce_str>");
        xmlString.append(nonce_str);
        xmlString.append("</nonce_str>");

        xmlString.append("<notify_url>");
        xmlString.append(notify_url);
        xmlString.append("</notify_url>");

        xmlString.append("<product_id>");
        xmlString.append(product_id);
        xmlString.append("</product_id>");

        xmlString.append("<out_trade_no>");
        xmlString.append(out_trade_no);
        xmlString.append("</out_trade_no>");

        xmlString.append("<spbill_create_ip>");
        xmlString.append(spbill_create_ip);
        xmlString.append("</spbill_create_ip>");

        xmlString.append("<total_fee>");
        xmlString.append(total_fee);
        xmlString.append("</total_fee>");

        xmlString.append("<trade_type>");
        xmlString.append(trade_type);
        xmlString.append("</trade_type>");

        xmlString.append("<sign>");
        xmlString.append(sign);
        xmlString.append("</sign>");



        xmlString.append("</xml>");



        System.out.println(xmlString.toString());

        HttpEntity  requestEntity = new HttpEntity(xmlString.toString(), requestHeader);
        String result = restTemplate.postForObject(url, requestEntity, String.class);

        Map map = doXMLParse(result);

        String prepay_id = (String) map.get("prepay_id");
        Long timeStamp = System.currentTimeMillis() / 1000;
        String nonceStr=getRandomStringByLength(13);

        Map<String,String> resultMap=new HashMap<String, String>();
        Map<String,String> signMap=new HashMap<String, String>();
        signMap.put("appid",appid);
        signMap.put("partnerid",mch_id);
        signMap.put("prepayid",prepay_id);
        signMap.put("package","Sign=WXPay");
        signMap.put("noncestr",nonceStr);
        signMap.put("timestamp",timeStamp+"");



        resultMap.put("appid",appid);
        resultMap.put("mch_id",mch_id);
        resultMap.put("prepayId",prepay_id);
        resultMap.put("nonceStr",nonceStr);
        resultMap.put("timeStamp",timeStamp+"");
        String linkString = createLinkString(signMap);
        resultMap.put("sign", sign(linkString, key, "utf-8").toUpperCase());
        resultMap.put("partnerId",mch_id);
        resultMap.put("packageValue","Sign=WXPay");






        return JSONObject.toJSONString(resultMap);



    }


}
